import { isSameNode } from "./vdom";

export function createElm(vnode) {
  let { tag, data, children, text } = vnode;
  if (typeof tag === "string") {
    vnode.el = document.createElement(tag);
    patchProps(vnode.el, {}, data);
    children.forEach((child) => {
      vnode.el.appendChild(createElm(child));
    });
  } else {
    vnode.el = document.createTextNode(text);
  }

  return vnode.el;
}
export function patchProps(el, oldProps, props) {
  //老的属性中有，新的没有，删除老的
  let oldStyles = oldProps.style || {};
  let newStyles = props.style || {};
  // 老的样式有，新的没有，删除
  for (const key in oldStyles) {
    if (!newStyles[key]) {
      el.style[key] = "";
    }
  }
  //新的覆盖老的
  for (const key in oldProps) {
    if (!props[key]) {
      el.removeAttribute(key);
    }
  }

  for (const key in props) {
    if (key === "style") {
      for (const styleName in props.style) {
        el.style[styleName] = props.style[styleName];
      }
    } else {
      el.setAttribute(key, props[key]);
    }
  }
}
export function patch(oldVNode, vnode) {
  const isRealElement = oldVNode.nodeType;
  if (isRealElement) {
    const elm = oldVNode; //获取真实元素
    const parentElm = elm.parentNode;
    let newElm = createElm(vnode);
    parentElm.insertBefore(newElm, elm.nextSibling); //插入节点
    parentElm.removeChild(elm); //删除老节点
    return newElm;
  } else {
    // diff算法
    // diff算法是一个平级比对算法，父节点和父节点对比
    return patchVnode(oldVNode, vnode);
  }
}

function patchVnode(oldVNode, vnode) {
  // 1.两个节点不是同一个节点，直接删除老的换上新的
  // 2.两个几点是同一个节点，判断节点的tag和key，比较两个节点的属性是否有差异，复用老街店，将差异的属性更替
  // 3.节点比较完毕后就替换子节点
  if (!isSameNode(oldVNode, vnode)) {
    // 用老节点的父亲替换;
    let el = createElm(vnode);
    oldVNode.el.parentNode.replaceChild(el, oldVNode.el);
    return el;
  }

  //文本的情况
  let el = (vnode.el = oldVNode.el); //复用老节点元素
  if (!oldVNode.tag) {
    if (oldVNode.text !== vnode.text) {
      el.textContent = vnode.text;
    }
  }

  //是标签，需要比对标签的属性
  patchProps(el, oldVNode.data, vnode.data);

  let oldChildren = oldVNode.children || [];
  let newChildren = vnode.children || [];

  if (oldChildren.length > 0 && newChildren.length > 0) {
    // 完整的diff算法，比较两个节点的儿子
    updateChildren(el, oldChildren, newChildren);
  } else if (newChildren.length > 0) {
    // 老的没有，新的有
    mountChildren(el, newChildren);
  } else if (oldChildren.length > 0) {
    // 新的没有，老的有，删除
    el.innerHTML = "";
  }
  return el;
}

function mountChildren(el, newChildren) {
  for (let i = 0; i < newChildren.length; i++) {
    let child = newChildren[i];
    el.appendChild(createElm(child));
  }
}

function updateChildren(el, oldChildren, newChildren) {
  // vue2采用双指针方式比较两个节点;
  let oldStartIndex = 0;
  let newStartIndex = 0;
  let oldEndIndex = oldChildren.length - 1;
  let newEndIndex = newChildren.length - 1;

  let oldStartVnode = oldChildren[0];
  let newStartVnode = newChildren[0];

  let oldEndVnode = oldChildren[oldEndIndex];
  let newEndVnode = newChildren[newEndIndex];

  // console.log(oldStartVnode, newStartVnode, oldEndVnode, newEndVnode);
}
